package ynwx.libaray.utils;

import android.content.Context;
import android.os.Environment;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * TODO Error message is logged when an uncaught exception occurs.
 *
 * @author gaoyuan
 */
public class CrashHandler implements UncaughtExceptionHandler {
    private static final String TAG = LogUtil.TAG + "CrashHandler";
    private static final boolean D = true;
    private static final CrashHandler instance = new CrashHandler();
    private UncaughtExceptionHandler mExceptionHandler;
    private Context mContext;
    private Map<String, String> info = new HashMap<String, String>();
    private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.CHINA);

    private CrashHandler() {
    }

    public static CrashHandler getInstance() {
        return instance;
    }

    public void init(Context context) {
        mContext = context;
        mExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        // TODO Auto-generated method stub
        ex.printStackTrace();
        if (!handleException(ex) && mExceptionHandler != null) {
            mExceptionHandler.uncaughtException(thread, ex);
        } else {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            android.os.Process.killProcess(android.os.Process.myPid());
            System.exit(1);
        }
    }

    public boolean handleException(Throwable ex) {
        if (ex == null)
            return false;
        saveCrashInfo2File(ex);
        return true;
    }

    /**
     * save error log to SDCard
     *
     * @param ex
     */
    private void saveCrashInfo2File(Throwable ex) {
        if (D) LogUtil.d(TAG, "saveCrashInfo2File");
        StringBuffer buffer = new StringBuffer();
        for (Map.Entry<String, String> entry : info.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            buffer.append(key + "=" + value + "\r\n");
        }
        Writer writer = new StringWriter();
        PrintWriter pw = new PrintWriter(writer);
        ex.printStackTrace(pw);
        Throwable cause = ex.getCause();
        while (cause != null) {
            cause.printStackTrace(pw);
            cause = cause.getCause();
        }
        pw.close();
        String result = writer.toString();
        buffer.append(result);
        long timetamp = System.currentTimeMillis();
        String time = format.format(new Date());
        File sdcardDir = Environment.getExternalStorageDirectory();
        String path = sdcardDir.getPath() + "/jny/crash";
        String fileName = "crash-" + time + "-" + timetamp + ".txt";
        File resultPath = new File(path);
        if (!resultPath.exists()) {
            resultPath.mkdir();
        }
        File saveFile = new File(resultPath, fileName);
        try {
            FileOutputStream outStream = new FileOutputStream(saveFile);
            outStream.write(buffer.toString().getBytes());
            outStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
//        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
//            try {
//                File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
//                if (D) LogUtil.i(TAG, dir.toString());
//                if (!dir.exists())
//                    dir.mkdir();
//                FileOutputStream fos = new FileOutputStream(new File(dir, fileName));
//                fos.write(buffer.toString().getBytes());
//                fos.close();
//            } catch (FileNotFoundException e) {
//                // TODO Auto-generated catch block
//                e.printStackTrace();
//            } catch (IOException e) {
//                // TODO Auto-generated catch block
//                e.printStackTrace();
//            }
//        }
    }

}
